import { isObject } from '@vue/shared';
import * as CryptoJS from 'crypto-js';
import dayjs from 'dayjs';

/**
 * @description 获取元素节点信息（在组件中的元素必须要传ctx）
 * @param  { String } selector 选择器 '.app' | '#app'
 * @param  { Boolean } all 是否多选
 * @param  { ctx } context 当前组件实例
 */
export const getRect = (selector: string, all = false, context?: any) => {
  return new Promise((resolve, reject) => {
    let query = uni.createSelectorQuery();
    if (context) {
      query = uni.createSelectorQuery().in(context);
    }
    query[all ? 'selectAll' : 'select'](selector)
      .boundingClientRect(function (rect) {
        if (all && Array.isArray(rect) && rect.length) {
          return resolve(rect);
        }
        if (!all && rect) {
          return resolve(rect);
        }
        reject('找不到元素');
      })
      .exec();
  });
};

/**
 * @description 获取当前页面实例
 */
export function currentPage() {
  const pages = getCurrentPages();
  const currentPage = pages[pages.length - 1];
  return currentPage || {};
}

/**
 * @description 后台选择链接专用跳转
 */
interface Link {
  path: string;
  name?: string;
  type: string;
  isTab: boolean;
  query?: Record<string, any>;
}

export enum LinkTypeEnum {
  'SHOP_PAGES' = 'shop',
  'CUSTOM_LINK' = 'custom',
}

export function navigateTo(
  link: Link | string,
  navigateType: 'navigateTo' | 'reLaunch' = 'navigateTo',
) {
  // const url = link.query ? `${link.path}?${objectToQuery(link.query)}` : link.path;
  let url = '';
  if (typeof link === 'string') {
    url = link;
  } else {
    url = link.query ? `${link.path}?${objectToQuery(link.query)}` : link.path;
  }
  switch (navigateType) {
    case 'navigateTo':
      uni.navigateTo({ url });
      break;
    case 'reLaunch':
      uni.reLaunch({ url });
      break;

    default:
      uni.navigateTo({ url });
      break;
  }
  // navigateType == 'navigateTo' && uni.navigateTo({ url });
  // navigateType == 'reLaunch' && uni.reLaunch({ url });
}

/**
 * @description 是否为空
 * @param {unknown} value
 * @return {Boolean}
 */
export const isEmpty = (value: unknown) => {
  return value == null && typeof value === 'undefined';
};

/**
 * @description 对象格式化为Query语法
 * @param { Object } params
 * @return {string} Query语法
 */
export function objectToQuery(params: Record<string, any>): string {
  let query = '';
  for (const props of Object.keys(params)) {
    const value = params[props];
    const part = `${encodeURIComponent(props)}=`;
    if (!isEmpty(value)) {
      console.log(encodeURIComponent(props), isObject(value));
      if (isObject(value)) {
        for (const key of Object.keys(value)) {
          if (!isEmpty(value[key])) {
            const params = `${props}[${key}]`;
            const subPart = `${encodeURIComponent(params)}=`;
            query += `${subPart + encodeURIComponent(value[key])}&`;
          }
        }
      } else {
        query += `${part + encodeURIComponent(value)}&`;
      }
    }
  }
  return query.slice(0, -1);
}

/**
 * @description 格式化输出价格
 * @param  { string } price 价格
 * @param  { string } take 小数点操作
 * @param  { string } prec 小数位补
 */
export function formatPrice({ price, take = 'all', prec = undefined }: any) {
  let [integer, decimals = ''] = `${price}`.split('.');

  // 小数位补
  if (prec !== undefined) {
    const LEN = decimals.length;
    for (let i = prec - LEN; i > 0; --i) decimals += '0';
    decimals = decimals.substr(0, prec);
  }

  switch (take) {
    case 'int':
      return integer;
    case 'dec':
      return decimals;
    case 'all':
      return `${integer}.${decimals}`;
  }
}

/**
 * @description 组合异步任务
 * @param  { string } task 异步任务
 */

export function series(...task: Array<(_arg: any) => any>) {
  return function (): Promise<any> {
    return new Promise((resolve, reject) => {
      const iteratorTask = task.values();
      const next = (res?: any) => {
        const nextTask = iteratorTask.next();
        if (nextTask.done) {
          resolve(res);
        } else {
          Promise.resolve(nextTask.value(res)).then(next).catch(reject);
        }
      };
      next();
    });
  };
}

/**
 * @description 添加单位
 * @param {String | Number} value 值 100
 * @param {String} unit 单位 px em rem
 */
export const addUnit = (value: string | number, unit = 'rpx') => {
  return !Object.is(Number(value), NaN) ? `${value}${unit}` : value;
};

/**
 * 自动适配不同的后端架构
 * 1. 例如 /act/oa/task ,在微服务架构保持不变,在单体架构编程 /admin/oa/task
 * 2. 特殊 /gen/xxx ,在微服务架构、单体架构编程 都需保持不变
 *
 * @param originUrl 原始路径
 */
export const adaptationUrl = (originUrl?: string) => {
  // 微服务架构 不做路径转换,为空不做路径转换
  const isMicro = import.meta.env.VITE_IS_MICRO;
  if (isEmpty(isMicro) || isMicro === 'true') {
    return originUrl;
  }

  // 验证码服务
  if (originUrl?.startsWith('/code/')) {
    return `/admin${originUrl}`;
  }

  // 如果是代码生成服务，不做路径转换
  if (originUrl?.startsWith('/gen')) {
    return originUrl;
  }
  // 转为 /admin 路由前缀的请求
  return `/admin/${originUrl?.split('/').splice(2).join('/')}`;
};

/**
 *加密处理
 */
export function encryption(src: string, keyWord: string) {
  const key = CryptoJS.enc.Utf8.parse(keyWord);
  // 加密
  const encrypted = CryptoJS.AES.encrypt(src, key, {
    iv: key,
    mode: CryptoJS.mode.CFB,
    padding: CryptoJS.pad.NoPadding,
  });
  return encrypted.toString();
}

/**
 *加密处理
 */
export function encryptionBase64(rawStr: string) {
  const wordArray = CryptoJS.enc.Utf8.parse(rawStr);
  return CryptoJS.enc.Base64.stringify(wordArray);
}

/**
 * @description 生成唯一 uuid
 * @return string
 */
export function generateUUID() {
  if (typeof crypto === 'object') {
    if (typeof crypto.randomUUID === 'function') {
      return crypto.randomUUID();
    }
    if (typeof crypto.getRandomValues === 'function' && typeof Uint8Array === 'function') {
      const callback = (c: any) => {
        const num = Number(c);
        return (num ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (num / 4)))).toString(
          16,
        );
      };
      return '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, callback);
    }
  }
  let timestamp = new Date().getTime();
  let performanceNow =
    (typeof performance !== 'undefined' && performance.now && performance.now() * 1000) || 0;
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
    let random = Math.random() * 16;
    if (timestamp > 0) {
      random = (timestamp + random) % 16 | 0;
      timestamp = Math.floor(timestamp / 16);
    } else {
      random = (performanceNow + random) % 16 | 0;
      performanceNow = Math.floor(performanceNow / 16);
    }
    return (c === 'x' ? random : (random & 0x3) | 0x8).toString(16);
  });
}

/**
 * 获取树形数据中的某一项
 * @param tree
 * @param value
 * @param props
 * @returns
 */
export const getTreeItem = function (tree, value, props = {}) {
  const defaultProps = { children: 'children', key: 'value' };
  const _props = { ...defaultProps, ...props };
  const handler = function (tree, value) {
    for (let i = 0; i < tree.length; i++) {
      if (tree[i][_props.key] == value) {
        return tree[i];
      }
      if (tree[i].children && tree[i][_props.children].length > 0) {
        const res = handler(tree[i][_props.children], value);
        if (res) {
          return res;
        }
      }
    }
  };
  return handler(tree, value);
};
export const timestampToTime = (timeStamp) => {
  const date = new Date(timeStamp);
  const Y = `${date.getFullYear()}-`;
  const M = `${date.getMonth() + 1 < 10 ? `0${date.getMonth() + 1}` : date.getMonth() + 1}-`;
  const D = `${date.getDate() < 10 ? `0${date.getDate()}` : date.getDate()} `;

  const h = `${date.getHours() < 10 ? `0${date.getHours()}` : date.getHours()}:`;
  const m = `${date.getMinutes() < 10 ? `0${date.getMinutes()}` : date.getMinutes()}:`;
  const s = `${date.getSeconds() < 10 ? `0${date.getSeconds()}` : date.getSeconds()} `;
  return `${Y}${M}${D}${h}${m}${s}`;
  // const D = `${date.getDate()} < 10 ? `0${date.getDate()}` : date.getDate()}-`;
};
export function strLen(str) {
  let len = 0;
  for (let i = 0; i < str.length; i++) {
    // 取出单个字符
    const c = str.charCodeAt(i);
    // 单字节加1 ，0~9，a~z
    if ((c >= 0x0001 && c <= 0x007e) || (c >= 0xff60 && c <= 0xff9f)) {
      len += 0.5;
    } else {
      len += 1;
    }
  }
  return len;
}

/**
 * @desc 时间转换
 * @param {Date, String, Number} date  时间
 * @param {String}   format		格式
 * @param {String}  emptyText  空值展示文字
 * */

export function formatByDayjs(date, format = 'YYYY-MM-DD', emptyText = '') {
  if (!date) return emptyText;
  const timeStamp = Number(date);
  return isNaN(timeStamp) ? dayjs(date).format(format) : dayjs(timeStamp).format(format);
}

export const getFileType = (url) => {
  const suffix = url.replace(/.*\./, '');
  if (
    ['jpg', 'jpeg', 'png', 'gif', 'svg', 'JPG', 'JPEG', 'PNG', 'GIF', 'SVG', 'WebP'].includes(
      suffix,
    )
  ) {
    return 'image';
  }
  if (['mp3', 'MP3', 'm4a', 'amr'].includes(suffix)) {
    return 'audio';
  }
  if (
    ['mp4', 'MP4', 'avi', 'AVI', 'mov', 'm4v', 'rm', 'rmvb', 'wmv', 'asf', 'asx'].includes(suffix)
  ) {
    return 'video';
  }
  return suffix;
};

// 跳转在线预览页面
export const previewOnline = (url) => {
  uni.navigateTo({
    url: `/pages/common/preview-online?url=${url}`,
    fail(e) {
      console.log(e);
    },
  });
};
// 下载文件
export function downloadFile(url, fileName) {
  uni.showLoading({
    title: '正在加载文件',
  });
  const header = {};
  if (fileName) {
    header['Content-Disposition'] = `attachment;filename=${fileName}`;
  }
  console.log(header);
  uni.downloadFile({
    url,
    timeout: 3000,
    header,
    success(res) {
      const filePath = res.tempFilePath;
      uni.openDocument({
        filePath,
        success(res) {
          uni.hideLoading();
        },
        fail(err) {
          uni.hideLoading();
          uni.showToast({
            title: '文件读取失败，请重试',
            icon: 'none',
          });
        },
      });
    },
    fail(err) {
      uni.hideLoading();
      uni.showToast({
        title: '文件加载失败，请重试',
        icon: 'none',
      });
    },
  });
}

export function downloadFileToLocal(src, name) {
  let fileName = src.substring(src.lastIndexOf('/') + 1);
  const fileType = fileName.split('.')[1];
  if (name) {
    fileName = `${name}.${fileType}`;
  }
  const fileDir = 'file://storage/emulated/0/';
  let filePath = `Download/${fileName}`;
  if (['jpg', 'jpeg', 'png', 'gif'].includes(fileType)) {
    filePath = `Pictures/${fileName}`;
  }
  return new Promise((resolve, reject) => {
    const dtask = plus.downloader.createDownload(
      src,
      {
        filename: fileDir + filePath,
      },
      (d, status) => {
        // d为下载的文件对象
        if (status == 200) {
          uni.hideLoading();
          setTimeout(() => {
            uni.showToast({
              icon: 'none',
              mask: false,
              title: `已保存到:${filePath}`, // 保存路径
              duration: 3000,
            });
          }, 500);
          // 下载成功,d.filename是文件在保存在本地的相对路径，使用下面的API可转为平台绝对路径
          const fileSaveUrl = plus.io.convertLocalFileSystemURL(d.filename);
          resolve(fileSaveUrl);
        } else {
          plus.downloader.clear(); // 清除下载任务
          reject(d);
        }
      },
    );
    dtask.start();
  });
}
